import tkinter as tk
from tkinter import ttk, messagebox
import tkinter.filedialog as fd
import json
import re

from history_db import get_all_records, update_remark, add_record, delete_record


class HistoryListFrame(ttk.LabelFrame):
    def __init__(self, master, on_select_record):
        super().__init__(master, text="历史记录", width=220,padding=10)
        self.on_select_record = on_select_record
        self.sort_reverse = True  # 默认倒序排列（最新的在前）
        self.search_pattern = ""  # 搜索模式
        self._build_ui()
        # self.refresh()  # 延迟到主窗口全部控件创建后再调用

    def _build_ui(self):
        # 搜索框
        search_frame = tk.Frame(self)
        search_frame.pack(fill=tk.X, pady=(0,5))
        tk.Label(search_frame, text="搜索:").pack(side=tk.LEFT, padx=(0,2))
        self.search_var = tk.StringVar()
        self.search_entry = ttk.Entry(search_frame, textvariable=self.search_var, width=15)
        self.search_entry.pack(side=tk.LEFT, padx=2)
        self.search_entry.bind('<Return>', self.on_search)
        search_btn = ttk.Button(search_frame, text="搜索", command=self.on_search, width=6)
        search_btn.pack(side=tk.LEFT, padx=2)
        clear_btn = ttk.Button(search_frame, text="清除", command=self.clear_search, width=6)
        clear_btn.pack(side=tk.LEFT, padx=2)
        
        btn_frame = tk.Frame(self)
        btn_frame.pack(fill=tk.X, pady=(0,5))
        export_btn = ttk.Button(btn_frame, text="导出", command=self.export_all)
        export_btn.pack(side=tk.LEFT, padx=2)
        import_btn = ttk.Button(btn_frame, text="导入", command=self.import_all)
        import_btn.pack(side=tk.LEFT, padx=2)
        analyze_btn = ttk.Button(btn_frame, text="分析", command=self.analyze_selected)
        analyze_btn.pack(side=tk.LEFT, padx=2)
        export_excel_btn = ttk.Button(btn_frame, text="导出到Excel", command=self.export_selected_to_excel)
        export_excel_btn.pack(side=tk.LEFT, padx=2)
        
        # 创建带滚动条的框架
        tree_frame = tk.Frame(self)
        tree_frame.pack(fill=tk.BOTH, expand=True)
        
        self.tree = ttk.Treeview(tree_frame, columns=("sel", "time", "remark", "com_port", "delete"), show="headings", height=10)
        self.tree.heading("sel", text="全选")
        self.tree.heading("time", text="测试时间 ↓")  # 默认倒序，显示向下箭头
        self.tree.heading("remark", text="备注")
        self.tree.heading("com_port", text="COM口")
        self.tree.heading("delete", text="删除")
        self.tree.column("sel", width=40, anchor='center')
        self.tree.column("time", width=120)
        self.tree.column("remark", width=80)
        self.tree.column("com_port", width=60, anchor='center')
        self.tree.column("delete", width=50)
        
        # 创建垂直滚动条
        scrollbar = ttk.Scrollbar(tree_frame, orient="vertical", command=self.tree.yview)
        self.tree.configure(yscrollcommand=scrollbar.set)
        
        # 布局Treeview和滚动条
        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.tree.bind("<<TreeviewSelect>>", self._on_select)
        self.tree.bind('<Button-1>', self._on_single_click)
        self.tree.bind('<Button-1>', self._on_click_heading, add='+')
        self.selected_ids = set()
        self._bind_scroll()

    def _bind_scroll(self):
        # 鼠标滚轮
        self.tree.bind('<MouseWheel>', self._on_scroll)
        self.tree.bind('<Button-4>', self._on_scroll)  # Linux
        self.tree.bind('<Button-5>', self._on_scroll)  # Linux
        # 键盘滚动
        self.tree.bind('<Key-Up>', self._on_scroll)
        self.tree.bind('<Key-Down>', self._on_scroll)
        self.tree.bind('<Prior>', self._on_scroll)  # PageUp
        self.tree.bind('<Next>', self._on_scroll)   # PageDown

    def _on_scroll(self, event):
        self._last_yview = self.tree.yview()
        print( self._last_yview )

    def refresh(self):
        # 优先用self._last_yview
        yview = getattr(self, '_last_yview', None)
        selected = self.tree.selection()
        for i in self.tree.get_children():
            self.tree.delete(i)
        
        # 获取所有记录
        all_records = get_all_records()
        # 应用搜索过滤
        self.records = self._filter_records(all_records)
        # 按时间排序
        self.records.sort(key=lambda x: x['time'], reverse=self.sort_reverse)
        
        for rec in self.records:
            checked = '☑' if rec['id'] in self.selected_ids else '☐'
            com_port = rec.get('com_port', '') or '无'
            self.tree.insert('', 'end', iid=rec['id'], values=(checked, rec['time'], rec['remark'], com_port, '删除'))
        
        # 恢复滚动位置
        print("--"+str(yview))
        if yview:
            self.tree.yview_moveto(yview[0])
            self._last_yview = None  # 用完清空
        # 恢复选中
        if selected:
            self.tree.selection_set(selected)
            self.tree.see(selected[0])
            self._on_select(None)

    def _on_select(self, event):
        sel = self.tree.selection()
        if not sel:
            return
        rec_id = int(sel[0])
        record = next((r for r in self.records if r['id'] == rec_id), None)
        if record:
            self._selected_id = rec_id
            self.on_select_record(record)

    def _on_single_click(self, event):
        # 统一处理单击事件
        region = self.tree.identify("region", event.x, event.y)
        if region != "cell":
            return
        col = self.tree.identify_column(event.x)
        rowid = self.tree.identify_row(event.y)
        if not rowid:
            return
            
        if col == '#1':  # 选择列 - 复选框
            self._handle_checkbox_click(rowid)
        elif col == '#3':  # 备注列 - 编辑备注
            self._on_click_remark(event)
        elif col == '#5':  # 删除列 - 删除记录
            self._handle_delete_click(rowid)
    
    def _handle_checkbox_click(self, rowid):
        # 处理复选框点击
        rec_id = int(rowid)
        if rec_id in self.selected_ids:
            self.selected_ids.remove(rec_id)
        else:
            self.selected_ids.add(rec_id)
        self.update_checkbox_ui()  # 只更新checkbox显示
        # 选中后自动触发详情显示
        self.tree.selection_set(rowid)
        self._on_select(None)
    
    def _handle_delete_click(self, rowid):
        # 处理删除按钮点击
        if tk.messagebox.askyesno("确认删除", "确定要删除这条历史记录吗？"):
            delete_record(int(rowid))
            self.refresh()

    def _on_click_heading(self, event):
        # 点击标题排序或全选
        region = self.tree.identify("region", event.x, event.y)
        if region != "heading":
            return
        col = self.tree.identify_column(event.x)
        if col == '#1':  # 全选列
            self.toggle_select_all()
        elif col == '#2':  # 测试时间列
            self.sort_reverse = not self.sort_reverse
            # 更新标题显示排序状态
            sort_indicator = " ↓" if self.sort_reverse else " ↑"
            self.tree.heading("time", text="测试时间" + sort_indicator)
            self.refresh()

    def _on_click_remark(self, event):
        # 单击备注列弹出输入框编辑
        region = self.tree.identify("region", event.x, event.y)
        if region != "cell":
            return
        col = self.tree.identify_column(event.x)
        if col != '#3':  # 备注列
            return
        rowid = self.tree.identify_row(event.y)
        if not rowid:
            return
        
        # 获取当前备注内容
        current_remark = self.tree.set(rowid, "remark")
        
        # 创建输入对话框
        dialog = tk.Toplevel(self.tree)
        dialog.title("编辑备注")
        dialog.resizable(False, False)
        dialog.transient(self.tree.winfo_toplevel())
        
        # 先隐藏对话框，避免闪烁
        dialog.withdraw()
        
        # 设置大小和位置
        width, height = 400, 150
        screen_width = dialog.winfo_screenwidth()
        screen_height = dialog.winfo_screenheight()
        x = (screen_width // 2) - (width // 2)
        y = (screen_height // 2) - (height // 2)
        dialog.geometry(f"{width}x{height}+{x}+{y}")
        
        # 设置模态
        dialog.grab_set()
        
        # 创建界面元素
        tk.Label(dialog, text="请输入备注内容:", font=("微软雅黑", 10)).pack(pady=10)
        
        entry = tk.Entry(dialog, font=("微软雅黑", 10), width=40)
        entry.pack(pady=5, padx=20, fill='x')
        entry.insert(0, current_remark)
        entry.select_range(0, tk.END)
        
        # 按钮框架
        btn_frame = tk.Frame(dialog)
        btn_frame.pack(pady=15)
        
        def save_remark():
            new_remark = entry.get().strip()
            self.tree.set(rowid, "remark", new_remark)
            update_remark(int(rowid), new_remark)
            dialog.destroy()
            self.refresh()
        
        def cancel_edit():
            dialog.destroy()
        
        # 确定和取消按钮
        tk.Button(btn_frame, text="确定", command=save_remark, 
                 font=("微软雅黑", 9), width=8).pack(side='left', padx=5)
        tk.Button(btn_frame, text="取消", command=cancel_edit, 
                 font=("微软雅黑", 9), width=8).pack(side='left', padx=5)
        
        # 绑定回车键确定，ESC键取消
        entry.bind('<Return>', lambda e: save_remark())
        dialog.bind('<Escape>', lambda e: cancel_edit())
        
        # 显示对话框
        dialog.deiconify()
        entry.focus()

    def update_checkbox_ui(self):
        # 只更新checkbox列，不重载数据
        for rec in getattr(self, 'records', []):
            checked = '☑' if rec['id'] in self.selected_ids else '☐'
            self.tree.set(rec['id'], "sel", checked)
    
    def toggle_select_all(self):
        """切换全选/取消全选状态"""
        if not hasattr(self, 'records') or not self.records:
            return
        
        # 检查当前是否全部选中
        all_ids = {rec['id'] for rec in self.records}
        is_all_selected = all_ids.issubset(self.selected_ids)
        
        if is_all_selected:
            # 如果全部选中，则取消全选
            self.selected_ids.clear()
        else:
            # 如果不是全部选中，则全选
            self.selected_ids.update(all_ids)
        
        # 更新UI显示
        self.update_checkbox_ui()

    def on_search(self, event=None):
        """执行搜索"""
        search_text = self.search_var.get().strip()
        self.search_pattern = search_text
        self.refresh()

    def clear_search(self):
        """清除搜索"""
        self.search_var.set("")
        self.search_pattern = ""
        self.refresh()

    def _filter_records(self, records):
        """根据搜索模式过滤记录"""
        if not self.search_pattern:
            return records
        
        filtered_records = []
        try:
            # 编译正则表达式，忽略大小写
            pattern = re.compile(self.search_pattern, re.IGNORECASE)
            for record in records:
                remark = record.get('remark', '')
                if pattern.search(remark):
                    filtered_records.append(record)
        except re.error:
            # 如果正则表达式无效，则进行普通字符串匹配
            search_lower = self.search_pattern.lower()
            for record in records:
                remark = record.get('remark', '').lower()
                if search_lower in remark:
                    filtered_records.append(record)
        
        return filtered_records

    def export_all(self):
        # 检查是否有勾选的记录
        if not self.selected_ids:
            messagebox.showinfo("提示", "请勾选要导出的记录")
            return
        
        # 只导出勾选的记录
        all_records = get_all_records()
        selected_records = [r for r in all_records if r['id'] in self.selected_ids]
        
        # 移除id字段
        for r in selected_records:
            if 'id' in r:
                del r['id']
        
        file_path = fd.asksaveasfilename(defaultextension='.json', filetypes=[('JSON文件', '*.json')])
        if not file_path:
            return
        with open(file_path, 'w', encoding='utf-8') as f:
            json.dump(selected_records, f, ensure_ascii=False, indent=2)
        messagebox.showinfo("成功", f"已导出 {len(selected_records)} 条记录")

    def import_all(self):
        file_path = fd.askopenfilename(filetypes=[('JSON文件', '*.json')])
        if not file_path:
            return
        with open(file_path, 'r', encoding='utf-8') as f:
            records = json.load(f)
        for r in records:
            # 忽略id，允许重复导入
            add_record(r['time'], r.get('remark',''), r.get('params',{}), r.get('data',{}), r.get('channel_order',{}))
        self.refresh()

    def analyze_selected(self):
        if not self.selected_ids:
            messagebox.showinfo("提示", "请至少选择一条记录")
            return
        selected_records = [r for r in self.records if r['id'] in self.selected_ids]
        from ui.analyze_window import AnalyzeWindow
        AnalyzeWindow(self, selected_records)

    def export_selected_to_excel(self):
        import openpyxl
        import os
        import tkinter.filedialog as fd
        import datetime
        selected_records = [r for r in self.records if r['id'] in self.selected_ids]
        if not selected_records:
            from tkinter import messagebox
            messagebox.showinfo("提示", "请至少选择一条记录")
            return
        file_path = fd.asksaveasfilename(defaultextension='.xlsx', filetypes=[('Excel文件', '*.xlsx')])
        if not file_path:
            return
        wb = openpyxl.Workbook()
        ws = wb.active
        ws.title = "历史数据"
        # 写入参数表头
        ws.append(["导出时间", datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')])
        ws.append([])

        for idx,rec in enumerate(selected_records,1):
            param = rec.get('params', {})
            param_str = f"记录{idx} 测试时间: {rec['time']}\n备注: {rec.get('remark', '')}\n参数: {param}"
            ws.append([param_str])
            ws.append([])

        ws.append([])

        # 组装数据部分
        # 先找出所有通道
        all_channels = set()
        for rec in selected_records:
            data = rec.get('data', {})
            all_channels.update(data.keys())
        all_channels = sorted(all_channels, key=lambda x: int(x) if str(x).isdigit() else x)
        # 写表头
        header = []
        for idx, rec in enumerate(selected_records, 1):
            for ch in all_channels:
                header.append(f"记录{idx}-通道{ch}")
        ws.append(header)
        # 找出最长的数据长度
        max_len = 0
        for rec in selected_records:
            data = rec.get('data', {})
            for ch in all_channels:
                vals = data.get(ch, [])
                if len(vals) > max_len:
                    max_len = len(vals)
        # 写入数据
        for i in range(max_len):
            row = []
            for rec in selected_records:
                data = rec.get('data', {})
                for ch in all_channels:
                    vals = data.get(ch, [])
                    row.append(vals[i] if i < len(vals) else "")
            ws.append(row)
        try:
            wb.save(file_path)
            from tkinter import messagebox
            messagebox.showinfo("成功", f"数据已导出到: {os.path.basename(file_path)}")
        except Exception as e:
            from tkinter import messagebox
            messagebox.showerror("导出失败", str(e))